

//底层汇编文件
//线程切换汇编代码
//移植时需要处理, 根据平台修改
//将此文件的PendSV_Handler设置为PendSV中断调用
//适用于CortexM4F M7


  .syntax unified
  .section .text,"ax",%progbits


  //对外提供的接口
  .global PendSV_Handler                                         //软件中断, 其优先级必须设置为最低
  .global H_TS_LL_StartFirstThread                               //提供给C环境, 用于H_TS_LL_ThreadScheduleISR的初始化

  //引入声明
  .global H_TS_LL_ThreadScheduleISR                              //调度中断调用, 软件中断将执行其指向的代码
  .global H_TS_LL_Core_Instance                                  //指向当前运行的线程句柄, 它仅可能被H_TS_LL_CurrentThreadRefresh更新
  .global H_TS_LL_CurrentThreadRefresh                           //其指向的代码进行当前线程的切换(更新H_TS_LL_Core_Instance)


H_TS_LL_ThreadSwitch:
  LDR       R1,=H_TS_LL_Core_Instance                            //加载指向当前线程句柄的指针的地址
  LDR       R1,[R1]                                              //加载当前线程的栈指针的地址(当前线程句柄的指针)

  PUSH      {R1,LR}                                              //需要注意使栈8字节对齐(C环境的需求)
  BL        H_TS_LL_CurrentThreadRefresh                         //更新当前线程信息 其返回更新后的线程句柄
 //LDR       R0,=H_TS_LL_CurrentThreadRefresh
 //BLX       R0
  POP       {R1,LR}

  CMP       R0,R1                                                //线程是否切换
  IT        EQ
  BXEQ      LR                                                   //如果相等 没有发生线程切换 直接返回


 //开始保存旧线程的状态
  MRS       R2,PSP                                               //读线程栈指针

 //判断线程是否使用了FPU 如果使用了 保存浮点寄存器
  TST       LR,#0x00000010
  IT        EQ
  VSTMDBEQ  R2!,{S16-S31}

  STMDB     R2!,{R4-R11,LR}                                      //保存现场
  STR       R2,[R1]                                              //保存栈指针到旧线程的句柄


 //开始恢复新线程的状态
  LDR       R2,[R0]                                              //读取栈指针
  LDMIA     R2!,{R4-R11,LR}                                      //恢复现场

 //判断线程是否使用了FPU 如果使用了 恢复浮点寄存器
  TST       LR,#0x00000010
  IT        EQ
  VLDMIAEQ  R2!,{S16-S31}

  MSR       PSP,R2                                               //恢复堆栈指针


  BX        LR                                                   //状态已经恢复为新线程的状态, 直接返回


//启动第一个线程
.type H_TS_LL_StartFirstThread, %function
H_TS_LL_StartFirstThread:
  LDR       R0,=H_TS_LL_ThreadScheduleISR
  LDR       R1,=H_TS_LL_ThreadSwitch
  STR       R1,[R0]


  DSB
  ISB
  CPSID     I                                                    //对主堆栈进行设置时须关闭中断
  DSB
  ISB

  LDR       R0,=0xE000ED00                                       //SCB基地址
  LDR       R0,[R0,#8]                                           //VTOR
  LDR       R0,[R0]                                              //初始MSP
  MSR       MSP,R0                                               //MSP恢复初始值, 最大化中断可用堆栈

  MOV       R0,#0
  MSR       CONTROL,R0                                           //设置CONTROL 设置为特权级,使用MSP (主要是为了清除FPCA)

  DSB
  ISB
  CPSIE     I                                                    //开启中断
  DSB
  ISB


  LDR       R1,=H_TS_LL_Core_Instance                            //加载指向当前线程句柄的指针的地址
  LDR       R1,[R1]                                              //加载当前线程的栈指针的地址(当前线程句柄的指针)
  LDR       R2,[R1]                                              //读取栈指针

  LDMIA     R2!,{R4-R11,LR}                                      //恢复现场
  MSR       PSP,R2                                               //恢复堆栈指针


  BX        LR                                                   //状态已经恢复为新线程的状态, 直接返回


//需要将下面的方法设为PendSV中断调用
.type PendSV_Handler, %function
PendSV_Handler:
  LDR       R0,=H_TS_LL_ThreadScheduleISR
  LDR       R0,[R0]
  BX        R0



